package cn.cdeden.knowledge.service.impl;

import cn.cdeden.common.core.domain.R;
import cn.cdeden.common.core.utils.MapstructUtils;
import cn.cdeden.common.core.utils.page.TableDataInfo;
import cn.cdeden.common.mybatis.validator.QueryHelpMybatisPlus;
import cn.cdeden.common.satoken.utils.LoginHelper;
import cn.cdeden.knowledge.domain.FilesLabelRecord;
import cn.cdeden.knowledge.domain.dto.CoreConfigDto;
import cn.cdeden.knowledge.domain.dto.FilesLabelDto;
import cn.cdeden.knowledge.domain.dto.FilesLabelExistence;
import cn.cdeden.knowledge.domain.dto.FilesLabelQueryParam;
import cn.cdeden.knowledge.enums.FileLabelTypeEnums;
import cn.cdeden.knowledge.mapper.FilesLabelRecordMapper;
import cn.cdeden.knowledge.utils.CoreConfigUtils;
import cn.cdeden.knowledge.utils.PageUtil;
import cn.cdeden.knowledge.vo.FilesLabelQueryVO;
import cn.cdeden.system.api.model.LoginUser;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import io.undertow.util.BadRequestException;
import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.cdeden.knowledge.domain.FilesLabel;
import cn.cdeden.knowledge.mapper.FilesLabelMapper;
import cn.cdeden.knowledge.service.FilesLabelService;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
@AllArgsConstructor
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class FilesLabelServiceImpl extends ServiceImpl<FilesLabelMapper, FilesLabel> implements FilesLabelService{


    private final FilesLabelMapper filesUserLabelMapper;

    private final CoreConfigUtils coreConfigUtils;

    private final FilesLabelRecordMapper recordMapper;


    @Override
    public List<FilesLabelQueryVO> getEnterpriseLabel() {
        List<FilesLabelQueryVO> filesLabelQueryVOList = new ArrayList<>();
        List<FilesLabel> childFilesLabels = new ArrayList<>();
        List<FilesLabel> topFilesLabels = filesUserLabelMapper.selectList(new QueryWrapper<FilesLabel>().eq("parent_id", 0L).eq("label_type", "sys"));
        List<Long> topIds = topFilesLabels.stream().map(FilesLabel::getId).collect(Collectors.toList());
        if (!topIds.isEmpty()) {
            childFilesLabels = filesUserLabelMapper.selectList(new QueryWrapper<FilesLabel>().in("parent_id", topIds).eq("label_type", "sys"));
        }
        List<FilesLabel> finalChildFilesLabels = childFilesLabels;
        topFilesLabels.forEach(filesLabel -> {
            FilesLabelQueryVO filesLabelQueryVO = MapstructUtils.convert(filesLabel, FilesLabelQueryVO.class);
            List<FilesLabel> childFilesLabelList = finalChildFilesLabels.stream().filter(filesLabel1 -> filesLabel1.getParentId().equals(filesLabelQueryVO.getId())).collect(Collectors.toList());
            List<FilesLabelQueryVO> filesLabelQueryVOList1 = MapstructUtils.convert(childFilesLabelList, FilesLabelQueryVO.class);
            filesLabelQueryVO.setChildFilesLabelList(filesLabelQueryVOList1);
            filesLabelQueryVOList.add(filesLabelQueryVO);
        });
        return filesLabelQueryVOList;
    }

    @Override
    public TableDataInfo<FilesLabelDto> queryAllTeam(FilesLabelQueryParam query, Pageable pageable) {
        String teamId = query.getTeamId();
        if (StringUtils.isBlank(teamId)){
            throw new RuntimeException("缺失团队id");
        }

        IPage<FilesLabel> queryPage = PageUtil.toMybatisPage(pageable);
        QueryWrapper<FilesLabel> predicate = QueryHelpMybatisPlus.getPredicate(query);
        predicate.eq("team_id",teamId)
            .orderByDesc("update_time")
            .orderByDesc("create_Time")
        ;
        IPage<FilesLabel> page = filesUserLabelMapper.selectPage(queryPage, predicate);

        return MapstructUtils.convertTableDataInfo(TableDataInfo.build(page), FilesLabelDto.class);
    }

    @Override
    public boolean queryLabelTypeByIdExistence(FilesLabelExistence existence) {
        String labelType = existence.getLabelType();
        List<String> labelIds = existence.getLabelIds();
        if (CollectionUtils.isEmpty(labelIds)){
            return true;
        }
        LambdaQueryChainWrapper<FilesLabel> wrapper = this.lambdaQuery()
            .eq(FilesLabel::getLabelType, labelType)
            .in(FilesLabel::getId, labelIds)
            ;
        if (StringUtils.equals("team",labelType)){
            wrapper.eq(FilesLabel::getTeamId,existence.getTeamId());
        }else if (StringUtils.equals("sys",labelType)){

        }else{
            wrapper.eq(FilesLabel::getCreateId,existence.getUserId());
        }
        List<FilesLabel> list = wrapper.list();
        return  labelIds.size() == list.size() ;
    }

    @Override
    public TableDataInfo<FilesLabelDto> queryAll(FilesLabelQueryParam query, Pageable pageable) {
        LoginUser user = LoginHelper.getLoginUser();
//        FileUserDto user = FileUserUtils.getUser(); //用户信息
        String username = user.getUsername();
        String userId = Long.toString(user.getUserId());
        IPage<FilesLabel> queryPage = PageUtil.toMybatisPage(pageable);
        QueryWrapper<FilesLabel> predicate = QueryHelpMybatisPlus.getPredicate(query);
        predicate.eq("create_by",username).eq("create_id",userId)
            .orderByDesc("update_time")
            .orderByDesc("create_Time")
        ;
        IPage<FilesLabel> page = filesUserLabelMapper.selectPage(queryPage, predicate);
        TableDataInfo<FilesLabel> build = TableDataInfo.build(page);
        return MapstructUtils.convertTableDataInfo(build, FilesLabelDto.class);
    }

    @Override
    public FilesLabelDto insert(FilesLabelDto resources) throws BadRequestException {
        LoginUser user = LoginHelper.getLoginUser();
//        FileUserDto user = FileUserUtils.getUser(); //用户信息
        String username = user.getUsername();
        String userId = Long.toString(user.getUserId());
        FilesLabel entity = MapstructUtils.convert(resources, FilesLabel.class);
//        FilesLabel entity = ConvertUtil.convert(resources, FilesLabel.class);

        String labelCreate = userId;

        String labelType = resources.getLabelType();
        if (StringUtils.equalsIgnoreCase(labelType, FileLabelTypeEnums.user.getCode())) {
            if (getMaxNum() <= getCount(userId, username)){
                throw  new BadRequestException("以达到最大的 标签数量 请删除一些标签在添加");
            }
        }else if (StringUtils.equalsIgnoreCase(labelType, FileLabelTypeEnums.team.getCode())) {
            labelCreate = resources.getTeamId(); //如果是团队标签 修改为团队id
        }


        if (labelNameRepeat(labelCreate, username, resources.getLabelName(), labelType,resources.getParentId(),null)){
            throw  new BadRequestException("已有同名标签");
        }
        if (resources.getSort() == null  ) {
            entity.setSort(999);
        }

        entity.setCreateBy(username);
        entity.setCreateId(userId);
        entity.setCreateTime(new Date());
        boolean save = this.save(entity);
        if (save){
            return MapstructUtils.convert(entity, FilesLabelDto.class);
//            return ConvertUtil.convert(entity, FilesLabelDto.class);
        }

        return null;
    }


    private Integer getMaxNum(){
        CoreConfigDto config = coreConfigUtils.getByConfigCodeAfter("SY_USER_LABEL_MAX_NUM");
        Integer i = 100;
//        Integer i = new Integer(100);
        if (ObjectUtils.isNotEmpty(config)){
            try {
                i = Integer.valueOf(config.getConfigValue());
            }catch (Exception e){}
        }
        return i;
    }


    public Integer getCount(String userId, String username) {
        QueryWrapper<FilesLabel> wrapper = new QueryWrapper<FilesLabel>()
            .eq("create_id",userId)
            .eq("create_by",username)
            .eq("label_type",FileLabelTypeEnums.user.getCode())
            ;
        return (int) this.count(wrapper);
    }


    @Override
    public boolean labelNameRepeat(String userId,String username,String labelName ,String labelType,Long parentId,Long id){
        QueryWrapper<FilesLabel> wrapper = new QueryWrapper<FilesLabel>();
        wrapper.eq("label_name",labelName);
        if (StringUtils.equals(labelType, FileLabelTypeEnums.user.getCode())){
            wrapper = wrapper.eq("create_id",userId)
                .eq("create_by",username)
                .eq("label_type",labelType)
            ;
        }else if (StringUtils.equals(labelType, FileLabelTypeEnums.sys.getCode())){
            wrapper = wrapper.eq("label_type",labelType);
            if (parentId != null){
                wrapper.eq("parent_id",parentId);
            }

        }else if (StringUtils.equals(labelType, FileLabelTypeEnums.team.getCode())){
            wrapper = wrapper.eq("label_type",labelType)
                .eq("team_id",userId);
        }


        if (id !=null){
            wrapper = wrapper.ne("id",id);
        }

        List<FilesLabel> list = this.list(wrapper);
        return CollectionUtils.isNotEmpty(list);
    }

    @Override
    public boolean updateById(FilesLabelDto resources) throws BadRequestException {
        LoginUser user = LoginHelper.getLoginUser();
//        FileUserDto user = FileUserUtils.getUser(); //用户信息
        String username = user.getUsername();
        String userId = Long.toString(user.getUserId());

        Long id = resources.getId();

        FilesLabel byId = getById(id);
        if (ObjectUtils.isEmpty(byId)){
            throw new BadRequestException("无效的修改编号");
        }

        if (labelNameRepeat(userId, username, resources.getLabelName(),byId.getLabelType(),byId.getParentId(),id)){
            throw new BadRequestException("已有同名标签");
        }
        if (resources.getSort() == null  ) {
            resources.setSort(999);
        }
        FilesLabel entity = MapstructUtils.convert(resources, FilesLabel.class);
        entity.setUpdateBy(username);
        entity.setUpdateId(userId);
        entity.setUpdateTime(new Date());

        entity.setCreateBy(null);
        entity.setCreateId(null);
        entity.setCreateTime(null);

        return this.updateById(entity);
    }

    @Override
    public R deleteByIdsAndType(Set<Long> ids, String teamId, String labelType, boolean is) {
        LambdaQueryWrapper<FilesLabel> wrapper = new LambdaQueryWrapper<FilesLabel>()
            .in(FilesLabel::getId,ids)
            .eq(StringUtils.isNotBlank(teamId),FilesLabel::getTeamId,teamId)
            .eq(FilesLabel::getLabelType,labelType)
            ;
        List<FilesLabel> labels = this.list(wrapper);
        if (CollectionUtils.isNotEmpty(labels)){
            Set<Long> collect = labels.stream().map(FilesLabel::getId).collect(Collectors.toSet());
            LambdaQueryWrapper<FilesLabelRecord> queryWrapper = new LambdaQueryWrapper<FilesLabelRecord>()
                .in(FilesLabelRecord::getLabelId, collect);
            if (!is) {
                if ( recordMapper.selectCount(queryWrapper) > 0){
                    return R.fail("标签下有文件，不能删除");
//                    return BaseRespResult.errorResult("415","标签下有文件，不能删除");
                }
            }else {
                recordMapper.delete(queryWrapper);
            }
            this.remove(wrapper);
        }
        return R.ok();
    }
}
